package com.ninong.ker.admin.sevice.impl;

import com.aliyun.oss.OSSClient;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.ninong.ker.admin.domain.Storage;
import com.ninong.ker.admin.mapper.StorageMapper;
import com.ninong.ker.admin.service.dto.StorageDTO;
import com.ninong.ker.admin.sevice.StorageService;
import com.ninong.ker.common.auth.SecurityAdmin;
import com.ninong.ker.common.exception.CmdException;
import com.ninong.ker.common.oss.client.OssClientFactory;
import com.ninong.ker.common.oss.upload.IOssUpload;
import com.ninong.ker.common.oss.upload.OssUpload;
import com.ninong.ker.common.tools.CommonUtil;
import com.ninong.ker.common.tools.Constants;
import com.ninong.ker.common.tools.FileUtil;
import com.ninong.ker.common.tools.MyDateUtils;
import com.ninong.ker.common.user.OnlineUser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.net.FileNameMap;
import java.net.URLConnection;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 *
 * @author 鸠摩智
 * @date 2020年12月8日 上午10:21:39
 */
@Service
@Transactional(rollbackFor = RuntimeException.class)
public class StorageServiceImpl extends ServiceImpl<StorageMapper, Storage> implements StorageService {

	@Value("${cmd.file.path}")
	private String serverPath;

	@Value("${oss.accessKeySecret}")
	private String accessKeySecret;

	@Value("${oss.accessKeyId}")
	private String accessKeyId;

	@Value("${oss.endpoint}")
	private String endpoint;

	@Value("${oss.bucketName}")
	private String bucketName;

	@Value("${oss.path}")
	private String path;

	/**
	 * 附件保存在本地的路径
	 */
	@Value("${file.base-path}")
	private String fileBasePath;

	/**
	 * 附件保存的位置
	 */
	@Value("${file.save-location}")
	private String saveLocation;

	/**
	 * 附件大小限制
	 */
	@Value("${file.size}")
	private String fileSize;

	@Autowired
	private SecurityAdmin securityAdmin;

	@Override
	public PageInfo<Storage> listPage(StorageDTO dto) {
		OnlineUser onlineUser = securityAdmin.currentUser();
		String tenantId = onlineUser.getTenantId();
		PageHelper.startPage(dto.getCurrentPage(), dto.getPageSize());
		LambdaQueryWrapper<Storage> query = new LambdaQueryWrapper<>();
		query.eq(Storage::getDeleted, Constants.DEFAULT_YES);
		query.eq(Storage::getTenantId, tenantId);
		if (!StringUtils.isEmpty(dto.getRealName())) {
			query.like(Storage::getName, dto.getName());
		}
		List<Storage> storages = baseMapper.selectList(query);
		return new PageInfo<>(storages);
	}

	@Override
	public List<Storage> create(MultipartFile[] files) throws IOException {
		List<Storage> storages = Lists.newArrayList();
		// 存储在oss上
		if (Constants.FILE_SAVE_LOCATION_OSS.equals(saveLocation)) {
			for (MultipartFile multipartFile : files) {
				Storage storage =  saveFileOnOss(multipartFile);
				storages.add(storage);
			}

		} else {
			for (MultipartFile multipartFile : files) {
				Storage storage =  saveFileOnLocalSever(multipartFile);
				storages.add(storage);
			}
		}
		return storages;
	}
	
	@Override
	public Storage uploadSingleFile(MultipartFile multipartFile) throws IOException {
		// 存储在oss上
		if (Constants.FILE_SAVE_LOCATION_OSS.equals(saveLocation)) {
			return saveFileOnOss(multipartFile);
		} else {
			return saveFileOnLocalSever(multipartFile);
		}

	}


	private Storage saveFileOnOss(MultipartFile multipartFile) throws IOException {
		OnlineUser onlineUser = securityAdmin.currentUser();
		String tenantId = onlineUser.getTenantId();
		String suffix = FileUtil.getExtensionName(multipartFile.getOriginalFilename());
		String type = FileUtil.getFileType(suffix);
		String name = multipartFile.getOriginalFilename();
		String size = FileUtil.getSize(multipartFile.getSize());
		OSSClient ossClient = OssClientFactory.createOssClient(accessKeySecret, accessKeyId, endpoint);
		IOssUpload ossUpload = new OssUpload();
		String url = ossUpload.uploadInputStream(ossClient, bucketName,
				"give/" + UUID.randomUUID().toString() + "." + suffix, path, multipartFile.getInputStream());
//			File file = FileUtil.upload(multipartFile, serverPath +File.separator+ type +  File.separator);
//			if(ObjectUtil.isNull(file)){
//				throw new CmdException(BusinessEnum.UPLOAD_FAILURE);
//			}
//			Storage  storage = new  Storage(name, suffix, type+File.separator+file.getName(), type, size);
		Storage storage = new Storage(name, suffix, url, type, size, tenantId);
		// 文件存储在oss上
		storage.setLocation(Constants.FILE_SAVE_LOCATION_OSS);
		baseMapper.insert(storage);

		return storage;
	}
	
	private Storage saveFileOnLocalSever(MultipartFile multipartFile) {
		if (multipartFile == null) {
			throw new CmdException("文件不能为空");
		}
		if (multipartFile.getSize() >= Integer.parseInt(fileSize) * 1024 * 1024) {
			throw new CmdException("文件不能大于"+fileSize+"M");
		}
		// 原始文件名
		String fileName = multipartFile.getOriginalFilename();
		// 文件后缀
		String suffixName = fileName.substring(fileName.lastIndexOf("."));
		// 文件类型
		String fileType = this.getMimeType(fileName);
		// 文件大小
		String fileSize = FileUtil.getSize(multipartFile.getSize());
		// 新的文件名
		String newFileName = UUID.randomUUID().toString().toLowerCase() + suffixName;
		// 新的文件名
		newFileName = MyDateUtils.format(new Date(), MyDateUtils.DatePattern.PURE_DATETIME_PATTERN) + File.separator
				+ newFileName;
		// 拼接文件路劲
		String filePathName = fileBasePath + newFileName;
		// 判断文件保存是否存在
		File file = new File(filePathName);
		if (file.getParentFile() != null || !file.getParentFile().isDirectory()) {
			// 创建文件
			file.getParentFile().mkdirs();
		}
		try {
			multipartFile.transferTo(file);
		} catch (IOException e) {
			throw new CmdException("文件上传失败");
		}
		/*
		 * String thumbnailFilePathName = filePathName; // added by djx 去掉后缀中包含的.png字符串
		 * if (filePathName.contains(".png")) { thumbnailFilePathName =
		 * filePathName.replace(".png", ".jpg"); } long size = multipartFile.getSize();
		 * double scale = 1.0d; if (size >= 200 * 1024) { if (size > 0) { scale = (200 *
		 * 1024f) / size; } } try { if (size < 200 * 1024) {
		 * Thumbnails.of(filePathName).scale(1f).outputFormat("jpg").toFile(
		 * thumbnailFilePathName); } else {
		 * Thumbnails.of(filePathName).scale(1f).outputQuality(scale).outputFormat(
		 * "jpg") .toFile(thumbnailFilePathName); } } catch (Exception e1) { throw new
		 * CmdException("操作失败"); } String newNewFileName = newFileName; if
		 * (newFileName.contains(".png")) { newNewFileName =
		 * newNewFileName.replace(".png", ".jpg"); file.delete();// 删除 }
		 */
		Storage fileInfo = new Storage();
		fileInfo.setSize(fileSize);
		fileInfo.setSuffix(suffixName);
		fileInfo.setCreateTime(new Date());
		fileInfo.setName(fileName);
		fileInfo.setType(fileType);
		fileInfo.setUrl(newFileName);
		// 本地服务器存储
		fileInfo.setLocation(Constants.FILE_SAVE_LOCATION_LOCAL);
		return fileInfo;
	}

	

	/**
	 * 获取附件类型
	 * 
	 * @param fileName
	 * @return
	 */
	private String getMimeType(String fileName) {
		FileNameMap fileNameMap = URLConnection.getFileNameMap();
		String type = fileNameMap.getContentTypeFor(fileName);
		return type;
	}

	@Override
	public void delete(String[] ids) {
		List<String> idList = Arrays.asList(ids);
		idList.forEach(id -> {
			Storage entity = new Storage();
			entity.setId(id);
			entity.setDeleted(false);
			baseMapper.updateById(entity);
		});

	}

	/**
	 *
	 * 删除服务器的附件
	 * 
	 * @param filePath 图片文件
	 * @return
	 */
	public void deleteFile(String filePath) {
		if (CommonUtil.isZeroLengthTrimString(filePath)) {
			return;
		}
		try {
			// 拼接文件路劲
			String filePathName = fileBasePath + filePath;
			// 判断文件保存是否存在
			File file = new File(filePathName);
			file.delete();// 删除
		} catch (Exception e1) {

		}

	}

	
	

	@Override
	public void deleteFileByUrl(String url) {
		if (CommonUtil.isZeroLengthTrimString(url)) {
			return;
		}
		try {
			// 拼接文件路劲
			String filePathName = fileBasePath + url;
			// 判断文件保存是否存在
			File file = new File(filePathName);
			file.delete();// 删除
		} catch (Exception e1) {

		}

	}

	@Override
	public void deleteFileById(String id) {
		Storage fileInfo = baseMapper.selectById(id);
		this.deleteFileByUrl(fileInfo.getUrl());
		baseMapper.deleteById(id);
	}

	@Override
	public void saveFileInfo(List<StorageDTO> storageDtos, String relId, String relType) {
		LambdaQueryWrapper<Storage> query = new LambdaQueryWrapper<>();
		if(StringUtils.isNotEmpty(relType)) {
			query.eq(Storage::getRelType, relType);
		}
		query.eq(Storage::getRelId, relId);
		baseMapper.delete(query);
		OnlineUser onlineUser = securityAdmin.currentUser();
		String tenantId = onlineUser.getTenantId();
		if (storageDtos != null && storageDtos.size() > 0) {
			for (StorageDTO storageDTO : storageDtos) {
				Storage storage = new Storage();
				BeanUtils.copyProperties(storageDTO, storage);
				storage.setId(null);
				storage.setCreateTime(new Date());
				storage.setRelId(relId);
				storage.setRelType(relType);
				storage.setTenantId(tenantId);
				baseMapper.insert(storage);
			}
		}
	}

	@Override
	public List<Storage> getByIDAndType(String relId, String relType) {
		LambdaQueryWrapper<Storage> query = new LambdaQueryWrapper<>();
		if(StringUtils.isNotEmpty(relType)){
			query.eq(Storage::getRelType, relType);
		}
		query.eq(Storage::getRelId, relId);
		List<Storage> fileList = baseMapper.selectList(query);
		return fileList;

	}

}
